/*
 * pps_bom
 */
package com.pitop.project.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baidu.fsg.uid.UidGenerator;
import com.google.common.collect.Maps;
import com.pitop.core.base.BaseDAO;
import com.pitop.core.base.BaseSVImpl;
import com.pitop.core.entity.Page;
import com.pitop.core.exceptions.BaseException;
import com.pitop.core.exceptions.ProjectException;
import com.pitop.core.tools.StringTools;
import com.pitop.project.dao.ProjectBomDAO;
import com.pitop.project.dao.ProjectDAO;
import com.pitop.project.dao.ProjectLogDAO;
import com.pitop.project.dao.ProjectStaffDAO;
import com.pitop.project.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("projectSV")
@Slf4j
public class ProjectSVImpl extends BaseSVImpl<Project, Long> implements ProjectSV {

    @Autowired
    private ProjectDAO projectDAO;

    @Resource
    private UidGenerator uidGenerator;

    @Resource
    private ProjectLogDAO projectLogDAO;

    @Autowired
    private ProjectBomDAO projectBomDAO;

    @Autowired
    private ProjectStaffDAO projectStaffDAO;


    @Override
    protected BaseDAO getBaseDAO() {
        return projectDAO;
    }

    /**
     * 保存account对象
     *
     * @param entity 实体
     * @throws BaseException
     */
    @Override
    public void save(Project entity) throws BaseException {
        if (entity == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        if (StringUtils.isEmpty(entity.getName())) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (entity.getStartTime() == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        Project projectParent = null;
        if (StringUtils.isNotEmpty(entity.getPreCode())) {
            projectParent = projectDAO.loadByCode(entity.getPreCode());
            if (projectParent == null) {
                throw new ProjectException(BaseException.BaseExceptionEnum.Result_Not_Exist);
            } else {
                entity.setLevel(projectParent.getLevel() + 1);
            }
        } else {
            entity.setLevel(1);
        }

        //检查项目名称和项目代码是否存在
        Map<String, Object> params = new HashMap<>();
        params.put("name", entity.getName());
        Project project = projectDAO.load(params);
        if (project != null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Exists);
        }
        params.clear();
        params.put("projectCode", entity.getProjectCode());
        project = projectDAO.load(params);
        if (project != null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Exists);
        }

        entity.setCode(String.valueOf(uidGenerator.getUID()));
        entity.setCreateTime(new Date());
        entity.setState(ProjectState.Develop.name());
        super.save(entity);

        //添加日志
        ProjectLog projectLog = new ProjectLog();
        projectLog.setProjectCode(entity.getProjectCode());
        projectLog.setEvent(ProjectLogState.Create.name());
        projectLog.setOperateName(entity.getOperateName());
        projectLog.setOperateCode(entity.getOperateCode());
        projectLog.setSummary("账户" + entity.getOperateName() + "创建了项目:" + entity.getName());
        projectLog.setCreateTime(new Date());
        projectLogDAO.insert(projectLog);
    }

    @Override
    public void modify(Project entity) throws BaseException {
        if (entity == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (entity.getId() == null && StringTools.isEmpty(entity.getCode())) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        //检查修改后项目名称和修改后项目代码是否存在
        Map<String, Object> params = new HashMap<>();
        Project project;
//        if (StringTools.isNotEmpty(entity.getName())) {
//            params.put("name", entity.getName());
//            project = projectDAO.load(params);
//            if (project != null) {
//                throw new ProjectException(BaseException.BaseExceptionEnum.Exists);
//            }
//        }
//        if (StringTools.isNotEmpty(entity.getProjectCode())) {
//            params.clear();
//            params.put("projectCode", entity.getProjectCode());
//            project = projectDAO.load(params);
//            if (project != null) {
//                throw new ProjectException(BaseException.BaseExceptionEnum.Exists);
//            }
//        }
        Project projectParent;
        if (StringTools.isNotEmpty(entity.getPreCode())) {
            projectParent = loadByCode(entity.getPreCode());
            if (projectParent == null) {
                throw new ProjectException(BaseException.BaseExceptionEnum.Result_Not_Exist);
            } else {
                entity.setLevel(projectParent.getLevel() + 1);
            }
        } else {
            entity.setLevel(1);
        }

        //检查修改的对象是否存在
        project = load(entity.getId(), entity.getCode());
        if (project == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        //稳定或停用状态不能修改
        if (project.getState().equals(ProjectState.Stable.name()) || project.getState().equals(ProjectState.Stop.name())) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        projectDAO.update(entity);

        //添加日志
        ProjectLog projectLog = new ProjectLog();
        projectLog.setProjectCode(entity.getProjectCode());
        projectLog.setEvent(ProjectLogState.Modify.name());
        projectLog.setOperateName(entity.getOperateName());
        projectLog.setOperateCode(entity.getOperateCode());
        projectLog.setSummary("账户" + entity.getOperateName() + "修改了项目:" + entity.getName());
        projectLog.setCreateTime(new Date());
        projectLogDAO.insert(projectLog);
    }

    /**
     * 加载一个对象Project
     *
     * @param id
     * @param code 编码
     * @return Project
     */
    @Override
    public Project load(Long id, String code) {
        if (id == null && code == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return projectDAO.load(param);
    }

    /**
     * 加载一个对象Project,(将查询关联数据)
     *
     * @param id
     * @param code 编码
     * @return Project
     */
    @Override
    public Project get(Long id, String code) {
        if (id == null && code == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return projectDAO.getDetail(id, code);
    }

    /**
     * 加载一个对象Project 通过id
     *
     * @param id
     * @return Project
     */
    @Override
    public Project loadById(Long id) {
        if (id == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return projectDAO.loadById(id);
    }

    /**
     * 加载一个对象Project 通过code
     *
     * @param code 编码
     * @return Project
     */
    @Override
    public Project loadByCode(String code) {
        if (code == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Project project = projectDAO.getByCode(code);
        if (project != null && StringTools.isNotEmpty(project.getPreCode())) {
            Project preProject = projectDAO.loadByCode(project.getPreCode());
            project.setPreName(preProject.getName());
        }
        return project;
    }

    /**
     * 加载一个对象Project 通过name
     *
     * @param name 项目名称
     * @return Project
     */
    @Override
    public Project loadByName(String name) {
        return projectDAO.loadByName(name);
    }

    /**
     * 加载一个对象Project 通过projectCode
     *
     * @param projectCode 项目代码
     * @return Project
     */
    @Override
    public Project loadByProjectCode(String projectCode) {
        return projectDAO.loadByProjectCode(projectCode);
    }

    /**
     * 加载一个对象Project 通过id,(将查询关联数据)
     *
     * @param id
     * @return Project
     */
    @Override
    public Project getById(Long id) {
        if (id == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return projectDAO.getById(id);
    }

    /**
     * 加载一个对象Project 通过code,(将查询关联数据)
     *
     * @param code 编码
     * @return Project
     */
    @Override
    public Project getByCode(String code) {
        if (code == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Project project = projectDAO.getByCode(code);
        if (project != null && StringTools.isNotEmpty(project.getPreCode())) {
            Project preProject = projectDAO.loadByCode(project.getPreCode());
            project.setPreName(preProject.getName());
        }
        return project;
    }

    /**
     * 根据主键id,oldStates 共同更新 Project 的状态到newState状态
     *
     * @param id
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateById(Long id, ProjectState newState, ProjectState... oldStates) {
        if (id == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        projectDAO.updateStateById(id, new Date(), newState.name(), states);
    }

    /**
     * 根据主键code,oldStates 共同更新 Project 的状态到newState状态
     *
     * @param code      编码
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateByCode(String code, ProjectState newState, ProjectState... oldStates) {
        if (code == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        projectDAO.updateStateByCode(code, new Date(), newState.name(), states);
    }

    /**
     * 根据主键id 更新 Project 的状态到另一个状态
     *
     * @param id
     * @param state 状态
     */
    @Override
    public void updateById(Long id, ProjectState state) {
        if (id == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        projectDAO.updateById(id, state.name(), new Date());
    }

    /**
     * 根据主键code 更新 Project 的状态到另一个状态
     *  @param code  编码
     * @param state 状态
     */
    @Override
    public void updateByCode(String code, String state) {
        if (code == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        projectDAO.updateByCode(code, state, new Date());
    }


    /**
     * 删除对象Project
     *
     * @param id * @param code 编码
     * @return Project
     */
    @Override
    public void delete(Long id, String code) {
        if (id == null && code == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        projectDAO.delete(param);
    }


    /**
     * 查询Project分页
     *
     * @param project 对象
     * @param offset  查询开始行
     * @param limit   查询行数
     * @return List<Project>
     */
    @Override
    public List<Project> list(Project project, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }

        Map<String, Object> map = null;
        if (project != null) {
            map = JSON.parseObject(JSON.toJSONString(project, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        List<Project> projectList = projectDAO.list(map, new RowBounds(offset, limit));
        Map<String, Object> params = Maps.newHashMap();
        for (Project entity : projectList) {
            params.put("preCode", entity.getCode());
            if (projectDAO.count(params) > 0) {
                entity.setHasChildren(true);
            } else {
                entity.setHasChildren(false);
            }
        }
        return projectList;
    }

    @Override
    public int count(Project project) {
        Map<String, Object> map = null;
        if (project != null) {
            map = JSON.parseObject(JSON.toJSONString(project, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        return projectDAO.count(map);
    }

    /**
     * 查询Project分页
     *
     * @param id     * @param code  编码
     * @param offset 查询开始行
     * @param limit  查询行数
     * @return List<Project>
     */
    @Override
    public List<Project> list(Long id, String code, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        List<Project> projectList = projectDAO.list(param, new RowBounds(offset, limit));
        if (projectList.size() > 0) {
            for (Project project: projectList) {
                if(StringTools.isNotEmpty(project.getPreCode())) {
                    project.setPreName(projectDAO.loadByCode(project.getPreCode()).getName());
                }
            }
        }
        return  projectList;
    }

    @Override
    public int count(Long id, String code) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return projectDAO.count(param);
    }

    /**
     * copy项目
     * 1.验证数据合法性
     * 2.复制项目信息
     * 3.复制项目bom关联
     * 4.复制参与项目的员工
     * 5.插入项目日志
     *
     * @param code        项目编码
     * @param account
     * @param accountCode
     */
    @Override
    public void copy(String code, String account, String accountCode) {
        //1.验证数据合法性
        if (StringTools.isEmpty(code)) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Empty_Param);
        }
        Project project = projectDAO.getByCode(code);
        if (project == null) {
            throw new ProjectException(BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        //2.复制项目信息
        Project copyProject = project;
        copyProject.setId(null);
        copyProject.setCode(String.valueOf(uidGenerator.getUID()));
        copyProject.setName(project.getName() + "_copy");
        copyProject.setState(ProjectState.Develop.name());
        copyProject.setCreateTime(new Date());
        copyProject.setOperateCode(accountCode);
        copyProject.setOperateName(account);
        projectDAO.insert(copyProject);

        //3.复制项目bom关联
        List<ProjectBom> projectBoms = project.getProjectBomList();
        if (projectBoms.size() > 0) {
            for (ProjectBom projectBom : projectBoms) {
                projectBom.setId(null);
                projectBom.setProjectCode(copyProject.getProjectCode());
                projectBomDAO.insert(projectBom);
            }
        }

        //4.复制参与项目的员工
        List<ProjectStaff> projectStaffs = project.getProjectStaffList();
        if (projectStaffs.size() > 0) {
            for (ProjectStaff projectStaff : projectStaffs) {
                projectStaff.setId(null);
                projectStaff.setProjectCode(copyProject.getProjectCode());
                projectStaffDAO.insert(projectStaff);
            }
        }

        //5.保存日志信息
        String summary = "管理员" + account + "复制了项目" + project.getName();
        ProjectLog projectLog = new ProjectLog();
        projectLog.setProjectCode(copyProject.getProjectCode());
        projectLog.setCreateTime(new Date());
        projectLog.setOperateName(account);
        projectLog.setOperateCode(accountCode);
        projectLog.setSummary(summary);
        projectLogDAO.insert(projectLog);


    }

}
